package com.wryyyyy.real.impl;

import com.influxdb.client.InfluxDBClient;
import com.influxdb.client.QueryApi;
import com.influxdb.query.FluxTable;
import com.wryyyyy.entity.FoulWaterQuality;
import com.wryyyyy.real.IFoulWaterDao;
import com.wryyyyy.utils.FluxFilter;
import com.wryyyyy.utils.FluxResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

import static com.wryyyyy.utils.SystemConstants.FOUL_WATER_BUCKET;

@Slf4j
@Component
public class FoulWaterDao implements IFoulWaterDao {
    @Resource
    private InfluxDBClient influxDBClient;

    @Override
    public FoulWaterQuality getContent(List<String> factoryIds) {
        QueryApi queryApi = influxDBClient.getQueryApi();

        // 把factoryIds作为查询条件添加到flux
        StringBuilder factoryIdFilter = FluxFilter.getFactoryIdFilter(factoryIds);

        // 查询语句
        String flux = "from(bucket: \""+FOUL_WATER_BUCKET+"\")\n" +
                "  |> range(start: -24h)\n" +
                "  |> filter(fn: (r) => r[\"_measurement\"] == \"foul_water_quality\")\n" +
                factoryIdFilter + "\n" +
                "  |> drop(columns: [\"factory_id\"])\n" +
                "  |> mean()\n" +
                "  |> yield(name: \"result\")";

        // 处理返回结果
        List<FluxTable> tables = queryApi.query(flux);

        return FluxResult.toBean(tables, FoulWaterQuality.class);
    }

    @Override
    public Double getPassingRate(List<String> factoryIds, Boolean week) {
        QueryApi queryApi = influxDBClient.getQueryApi();

        StringBuilder factoryIdFilter = FluxFilter.getFactoryIdFilter(factoryIds);

        int start=24;
        if (week) start = 7*24;

        String flux = "t1=from(bucket: \""+FOUL_WATER_BUCKET+"\")\n" +
                "  |> range(start: -"+start+"h)\n" +
                "  |> filter(fn: (r) => r[\"_measurement\"] == \"foul_water_quality\")\n" +
                factoryIdFilter + "\n" +
                "  |> map(fn: (r)=> {\n" +
                "      return if ((r[\"_field\"] == \"COD\" and r[\"_value\"] > 50) or (r[\"_field\"] == \"BOD\" and r[\"_value\"] > 10) or (r[\"_field\"] == \"SS\" and r[\"_value\"] > 10) or (r[\"_field\"] == \"TP\" and r[\"_value\"] > 1) or (r[\"_field\"] == \"TN\" and r[\"_value\"] > 20) or (r[\"_field\"] == \"NH3_N\" and r[\"_value\"] > 8))\n" +
                "      then {\"passing\": 0} else {\"passing\":1}\n" +
                "    })\n" +
                "  |> sum(column: \"passing\")\n" +
                "t2=from(bucket: \"foul_water\")\n" +
                "  |> range(start: -24h)\n" +
                "  |> filter(fn: (r) => r[\"_measurement\"] == \"foul_water_quality\")\n" +
                "  |> map(fn: (r)=> {\n" +
                "      return {\"total\": 1}\n" +
                "    })\n" +
                "  |> sum(column: \"total\")\n" +
                "  union(tables: [t1,t2])";

        List<FluxTable> tables = queryApi.query(flux);

        return FluxResult.toPercentage(tables);
    }

    @Override
    public Map<LocalDateTime, Double> getAmount(List<String> factoryIds) {
        QueryApi queryApi = influxDBClient.getQueryApi();

        StringBuilder factoryIdFilter = FluxFilter.getFactoryIdFilter(factoryIds);

        String flux = "from(bucket: \""+FOUL_WATER_BUCKET+"\")\n" +
                "  |> range(start: -24h)\n" +
                "  |> filter(fn: (r) => r[\"_measurement\"] == \"foul_water_amount\")\n" +
                factoryIdFilter + "\n" +
                "  |> drop(columns: [\"factory_id\"])\n" +
                "  |> window(every: 2h)\n" +
                "  |> sum()\n" +
                "  |> yield(name: \"result\")";

        List<FluxTable> tables = queryApi.query(flux);

        return FluxResult.toEach(tables);
    }

    @Override
    public Double getTotalAmount(List<String> factoryIds, Boolean week) {
        QueryApi queryApi = influxDBClient.getQueryApi();

        StringBuilder factoryIdFilter = FluxFilter.getFactoryIdFilter(factoryIds);

        int start=24;
        if (week) start = 7*24;

        String flux = "from(bucket: \""+FOUL_WATER_BUCKET+"\")\n" +
                "  |> range(start: -"+start+"h)\n" +
                "  |> filter(fn: (r) => r[\"_measurement\"] == \"foul_water_amount\")\n" +
                factoryIdFilter + "\n" +
                "  |> drop(columns: [\"factory_id\"])\n" +
                "  |> sum()\n" +
                "  |> yield(name: \"result\")";

        List<FluxTable> tables = queryApi.query(flux);

        return FluxResult.toOneDouble(tables);
    }

    @Override
    public Double getTotalDosage(List<String> factoryIds, Boolean week) {
        QueryApi queryApi = influxDBClient.getQueryApi();

        StringBuilder factoryIdFilter = FluxFilter.getFactoryIdFilter(factoryIds);

        int start=24;
        if (week) start = 7*24;

        String flux = "from(bucket: \""+FOUL_WATER_BUCKET+"\")\n" +
                "  |> range(start: -"+start+"h)\n" +
                "  |> filter(fn: (r) => r[\"_measurement\"] == \"foul_water_dosage\")\n" +
                factoryIdFilter + "\n" +
                "  |> drop(columns: [\"factory_id\"])\n" +
                "  |> mean()\n" +
                "  |> yield(name: \"result\")";

        List<FluxTable> tables = queryApi.query(flux);

        return FluxResult.toOneDouble(tables);
    }

    @Override
    public Map<LocalDateTime, Double> getDosage(List<String> factoryIds) {
        QueryApi queryApi = influxDBClient.getQueryApi();

        StringBuilder factoryIdFilter = FluxFilter.getFactoryIdFilter(factoryIds);

        String flux = "from(bucket: \""+FOUL_WATER_BUCKET+"\")\n" +
                "  |> range(start: -24h)\n" +
                "  |> filter(fn: (r) => r[\"_measurement\"] == \"foul_water_dosage\")\n" +
                factoryIdFilter + "\n" +
                "  |> drop(columns: [\"factory_id\"])\n" +
                "  |> window(every: 2h)\n" +
                "  |> sum()\n" +
                "  |> yield(name: \"result\")";

        List<FluxTable> tables = queryApi.query(flux);

        return FluxResult.toEach(tables);
    }
}